package com.acoreful.ackitcloud.route;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.acoreful.ackitcloud.route.properties.DynamicRouteConfigProperties;
import com.acoreful.ackitcloud.route.properties.GatewayRouteProperties;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import io.netty.util.internal.StringUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.Yaml;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

@Slf4j
@AllArgsConstructor
public class NacosDynamicRouteListener implements InitializingBean {
    private  final DynamicRouteManger dynamicRouteManger;
    private final DynamicRouteConfigProperties dynamicRouteProperties;
    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            this.dynamicRouteListener();
        } catch (NacosException exception){
            log.error("update dynamicRoute error",exception);
        }
    }

    private void dynamicRouteListener() throws NacosException {
        String dataId=this.dynamicRouteProperties.getDataId();
        String group= dynamicRouteProperties.getGroup();
        String namespace=dynamicRouteProperties.getNamespace();
        Properties properties=new Properties();
        properties.setProperty(PropertyKeyConst.NAMESPACE,namespace);
        properties.put(PropertyKeyConst.SERVER_ADDR, dynamicRouteProperties.getServerAddr());
        properties.put(PropertyKeyConst.USERNAME, dynamicRouteProperties.getUsername());
        properties.put(PropertyKeyConst.PASSWORD, dynamicRouteProperties.getPassword());
        ConfigService configService = NacosFactory.createConfigService(properties);
        if (configService == null) {
            throw new NacosException(-1, "Get config service error!");
        }

        //Init routers.
        this.initRouters(configService,dataId,group);

        //Update routes.
        configService.addListener(dataId, group, new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                log.info(":cloud: update gateway start");
                boolean result = dynamicRouteManger.batchUpdate(getRoutes(configInfo));
                log.info(":cloud: update gateway end: {}", result);
            }
            @Override
            public Executor getExecutor() {
                return null;
            }
        });

    }

    private void initRouters(ConfigService configService,String dataId, String group) throws NacosException {
        log.info("init gateway start");
        String content = configService.getConfig(dataId, group, dynamicRouteProperties.getTimeout());
        List<RouteDefinition> routes = getRoutes(content);
        if (CollectionUtil.isEmpty(routes)) {
            return;
        }
        routes.forEach(route -> {
            Boolean result = dynamicRouteManger.add(route);
            log.info("load routes：{},{},{}", result?"成功":"失败", route.getId(), route);
        });
        log.info("init gateway end");
    }

    public List<RouteDefinition> getRoutes(String content) {
        if(StrUtil.isBlank(content)){
            return null;
        }
        Yaml yaml = new Yaml();
        GatewayRouteProperties gatewayRoute = yaml.loadAs(content, GatewayRouteProperties.class);
        return gatewayRoute != null ? gatewayRoute.getRoutes() : null;
    }
}
